【AWS IoT Greengrass V2】パブリックイメージの Docker コンテナをカスタムコンポーネントとして AWS からデプロイしてみる
前回は Docker コンテナをデバイス上でローカルからデプロイしてみました。
今回は同じコンテナを AWS 側からデプロイしてみたいと思います。前回同様、具体的な手順は下記のドキュメントを参考にしています。
注意点としては、上記ドキュメントのまま実施するとデプロイがエラーになる点です。
ドキュメントでは「ローカルデプロイ」→「AWSからデプロイ」という手順を想定しているようですが、ローカルでデプロイする前にアーティファクトやレシピを保存するディレクトリを作成する手順が抜けているので、そのまま実行するとエラーになります。
もしエラーになるようでしたら、前回の記事 を参考にしてみていただければと思います。
本記事で検証するデプロイパターン
デプロイパターンとして本記事で検証するのは下記の「2. パブリックイメージから Raspberry Pi に Docker コンテナを AWS からデプロイ」になります。その他のパターンについてはリンクから参照してください。
- Docker Hub のパブリックイメージから Raspberry Pi に Docker コンテナをローカルデプロイ
- Docker Hub のパブリックイメージから Raspberry Pi に Docker コンテナを AWS からデプロイ(本記事)
- Amazon ECR のプライベートイメージから Raspberry Pi に Docker コンテナをローカルデプロイ(予定)
- Amazon ECR のプライベートイメージから Raspberry Pi に Docker コンテナをAWSからデプロイ(予定)
検証内容の構成イメージ
前回とほとんど同じで、Docker Hub にあるPostgreSQL のパブリックイメージから Docker コンテナをデプロイします。
違うのはデプロイ指示を出す場所です。前回はコマンドを使ってローカルでデプロイしましたが、今回はデバイスにログインせずに AWS 側からデプロイを行います。
前提
前回の記事と同じになりますが、再掲します。
既存イメージの削除
何もない状態から試したいので、前回の記事で動作確認に使ったコンテナやイメージがあれば消して起きましょう。
コンテナを削除する場合は、docker rm
で消します。
$ docker rm [CONTAINER ID]
イメージの削除はdocker rmi
で消します。
$ docker rmi [IMAGE ID]
Docker 実行ユーザーの設定変更
Greengrass 経由での Docker 実行ユーザは、デフォルトで ggc_user
になるので、docker
グループにggc_user
を追加しておきます。
$ sudo usermod -aG docker ggc_user
レシピとアーティファクト用のディレクトリ削除
削除する必要はありませんが、ローカルデプロイ用のレシピなどがデバイス上にも存在すると、ややこしいので一旦消しておきます。
(存在していても参照されないだけですが…)
下記の通り何もない状態にしました。
(私の環境では他に動かしているコンポーネントがあるので、実際には他のコンポーネントのアーティファクトなどが存在します。)
. ├── artifacts └── recipes
IAM の権限追加
今回新たに追加となる前提条件です。
AWS 側からデプロイする場合、アーティファクトであるdocker-compose.yaml
を S3 からダウンロードする必要があるので、Greengrass の IAM Role に権限が追加で必要となります。
まず下記のような IAM ポリシーを作成します。今回は AWS CLI で実行したので下記ポリシーで component-artifact-policy.json
というファイルを PC 上に作成します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::[Your-S3-Bucket]/*" ] } ] }
次にこのポリシーをMyGreengrassV2ComponentArtifactPolicy
という名前で作成します。(好きな名前にしてください)
$ aws iam create-policy \ --policy-name MyGreengrassV2ComponentArtifactPolicy \ --policy-document file://component-artifact-policy.json
IAM ポリシーが作成できたら、Greengrass の IAM Role である GreengrassV2TokenExchangeRole
にアタッチします。
$ aws iam attach-role-policy \ --role-name GreengrassV2TokenExchangeRole \ --policy-arn arn:aws:iam::xxxxxxxxxxxx:policy/MyGreengrassV2ComponentArtifactPolicy
docker-compose.yaml の作成と S3 へ保存
前回と同じ内容でdocker-compose.yaml
を作成します。( PC 上の適当なところに一旦保存します)
version: '3' services: db: image: postgres:latest environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password ports: - 5432:5432
今回は、アーティファクトをS3からダウンロードするので、作成したdocker-compose.yaml
を適当な S3 バケットに保存します。
今回は 下記の通りs3://[Your-S3-Bucket]/docker-component/docker-compose.yaml
というパスで保存しました。
注意点としては、アーティファクトであるdocker-compose.yaml
を S3 に保存するパスの構成です。
python などで作ったカスタムコンポーネントを AWS からデプロイするときは、S3 上のアーティファクトの URI の指定としてローカルデプロイする場合と同様に、下記のような階層構成にする必要があります。
Artifacts: - Uri: s3://[YOUR-S3-BUCKET]/artifacts/com.example.MyComponent/1.0.0/sample.py
しかしDockerコンテナの場合、実体として動くアーティファクトはコンテナレジストリからダウンロードされるので、docker-compose.yaml
の保存場所としては上記の構成である必要はなく、今回設定したような下記のようなフォルダ構成でも問題ありません。
Artifacts: - Uri: s3://[YOUR-S3-Bucket]/docker-component/docker-compose.yaml
ただ、他のコンポーネントと同じフォルダ構成にした方が管理しやすい場面もあるかと思いますので、利用する際は一度検討していただくのがいいかと思います。
コンポーネントの作成
次に、AWS コンソールからコンポーネントを新規に作成します。
次の画面でレシピを YAML として入力します。
レシピの内容は下記になります。前回と同様に「Docker application manager」というパブリックコンポーネントが依存関係で必要なので、ComponentDependencies
として記載しています。
RecipeFormatVersion: '2020-01-25' ComponentName: com.example.MyDockerComposeComponent ComponentVersion: '1.0.0' ComponentDescription: 'A component that uses Docker Compose to run images from Docker Hub.' ComponentPublisher: Amazon ComponentDependencies: aws.greengrass.DockerApplicationManager: VersionRequirement: ~2.0.0 Manifests: - Platform: os: all Lifecycle: Run: docker-compose -f {artifacts:path}/docker-compose.yaml up Artifacts: - Uri: docker:postgres:latest - Uri: s3://[YOUR-S3-BUCKET]/docker-component/docker-compose.yaml
また、上記レシピのアーティファクトに先程 S3 に保存したdocker-compose.yaml
を指定しています。
コンポーネントのデプロイ
コンポーネントが作成できればデプロイします。
この後は、特に特別な手順はないので割愛します。
動作確認
デプロイが正常に終了したらデバイス上で動作確認します。PostgreSQL のコンテナが起動しています。
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 42329d89927b postgres:latest "docker-entrypoint.s…" 7 minutes ago Up 7 minutes 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp 100_db_1 Raspberry Pi 上でデータベースに接続もできました。 $ psql -h localhost -U postgres Password for user postgres: psql (11.12 (Raspbian 11.12-0+deb10u1), server 13.4 (Debian 13.4-1.pgdg100+1)) WARNING: psql major version 11, server major version 13. Some psql features might not work. Type "help" for help. postgres=#
ローカルでデプロイした場合と同様に、AWS 側からコンポーネントを削除するとコンテナも停止しました。
$ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 42329d89927b postgres:latest "docker-entrypoint.s…" 15 minutes ago Exited (0) 15 seconds ago 100_db_1
最後に
今回は、AWS 側からコンテナのコンポーネントをデプロイしてみました。
主な違いは下記のような点でしょうか。
- デバイスのローカル上にアーティファクトやレシピを準備する必要がない
- レシピにアーティファクトの URI を追加
- IAM 権限の追加
次回は Amazon ECR を使ってプライベートイメージの運用を想定した検証を行ってみたいと思います。